package graph;

import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import util.MyFormat;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.LineSegment;

import facility.Facility;

public class GraphEdge implements SpatialSearchTreeObject, Comparable {

	private int id;
	private GraphNode srcNode;
	private GraphNode destNode;
	private double score;
	List<Integer> fids;
	Set<Integer> routeIds;
	double weight;
	LineSegment ls ;
	// public GraphEdge(int id) {
	// this.id = id;
	// sourceNode = new double[2];
	// destNode = new double[2];
	// }

	public GraphEdge(int id, GraphNode srcNode, GraphNode destNode) {
		this.id = id;
		this.srcNode = srcNode;
		this.destNode = destNode;
		fids = new ArrayList<Integer>();
		routeIds = new HashSet<Integer>();
		
		//internal structure
		Coordinate p0 = new Coordinate(srcNode.x, srcNode.y);
		Coordinate p1 = new Coordinate(destNode.x, destNode.y);
		this.ls =  new LineSegment(p0, p1);
		this.weight = ls.getLength();
	}

	public void addFacilityId(Integer fid) {
		this.fids.add(fid);
	}

	public List<Integer> getFids() {
		return fids;
	}
	

	public Set<Integer> getRouteIds() {
		return routeIds;
	}

	public void setRouteIds(Set<Integer> routeIds) {
		this.routeIds = routeIds;
	}

	public void addRouteId(int routeId) {
		this.routeIds.add(routeId);
	}

	@Override
	public MBR getMBR() {
		double minX = Math.min(srcNode.x, destNode.x);
		double maxX = Math.max(srcNode.x, destNode.x);

		double minY = Math.min(srcNode.y, destNode.y);
		double maxY = Math.max(srcNode.y, destNode.y);

		double width = maxX - minX;
		double height = maxY - minY;

		return new MBR(minX, minY, width, height);
	}

	@Override
	public int getNumOfDimensions() {
		return 2;
	}

	@Override
	public double computeDistanceTo(double[] point) {
		return ls.distance(new Coordinate(point[0], point[1]));
	}

	@Override
	public boolean contains(MBR rect) {
		return this.getMBR().contains(rect);
	}

	@Override
	public int getId() {
		return id;
	}

	@Override
	public boolean intersects(Object obj) {
		if (obj instanceof GraphNode) {
			return getMBR().intersects(((GraphNode) obj).getMBR());
		} else if (obj instanceof GraphEdge) {
			return getMBR().intersects(((GraphEdge) obj).getMBR());
		} else
			return false;
	}

	@Override
	public boolean intersects(MBR r) {
		return this.getMBR().intersects(r);
	}

	@Override
	public boolean isContainedBy(MBR rect) {
		return rect.contains(this.getMBR());
	}

	@Override
	public boolean isOfSameType(SpatialSearchTreeObject obj) {
		if (obj instanceof GraphEdge) {
			return true;
		}
		return false;
	}

	public String toString() { // Always a good idea for debuging
		return "GE" + id + ":" + srcNode.toString() + "--"
				+ destNode.toString() + " score:" + this.score;
	}

	public GraphNode getSrcNode() {
		return srcNode;
	}

	public void setSrcNode(GraphNode srcNode) {
		this.srcNode = srcNode;
	}

	public GraphNode getDestNode() {
		return destNode;
	}

	public void setDestNode(GraphNode destNode) {
		this.destNode = destNode;
	}

	public void setId(int id) {
		this.id = id;
	}

	/**
	 * 
	 * @return length of the edge
	 */
	public double getWeight() {
		return this.weight;
	}

	public double getScore() {
		return score;
	}

	public void setScore(double score) {
		this.score = score;
	}

	public int getSrcId() {
		return this.getSrcNode().getId();
	}

	public int getDestId() {
		return this.getDestNode().getId();
	}

	@Override
	public int compareTo(Object arg0) {
		GraphEdge ge = (GraphEdge) arg0;
		if (this.score > ge.score)
			return -1;
		else if (this.score == ge.score)
			return 0;
		else
			return 1;
	}

}
